﻿using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using ConceptCorporateAdmin.Gui.Widgets;
using System.Text.RegularExpressions;
using System.IO;
using System.Threading;

namespace ConceptCorporateAdmin.Gui
{
    class Div
    {
        int startDiv = -1;
        int endDiv = -1;

        public Div() { }

        public Div(int start, int end)
        {
            startDiv = start;
            endDiv = end;
        }

        public int StartDiv
        {
            get { return startDiv; }
            set { startDiv = value; }
        }

        public int EndDiv
        {
            get { return endDiv; }
            set { endDiv = value; }
        }
    }

    public class Generator
    {
        TreeView ListaEntitati;
        String Text;
        DbActNormativ ActNormativ;
        ToolStripProgressBar pbar;

        public Generator( TreeView tree, string text, DbActNormativ act, ToolStripProgressBar pbar )
        {
            ListaEntitati    = tree;
            Text             = text;
            this.ActNormativ = act;
            this.pbar        = pbar;
        }

        public void generateTreeFromString()
        {
            pbar.Style = ProgressBarStyle.Marquee;
            string text = this.Text;
            //sterge nodurile precedente
            ListaEntitati.Nodes.Clear(); 
            EntitateTreeNode oldNod = null;
            //folosit la generarea de iduri pt ancore
            int element_index = 0;
            //parsuieste textul
            while (text.IndexOf("]") != -1)
            {
                int x = text.IndexOf("[");
                if (text[x + 1].Equals('*'))
                {
                    //facem substring in restul textului
                    text = text.Substring(x + 1);
                    int y = text.IndexOf("]");
                    //
                    string sub_part = text.Substring(0, y);
                    //aflam numarul de stelutze
                    int nrStelute = getNrOfChars('*', sub_part);
                    text = text.Substring(y + 1);
                    //preia titlul
                    String titlu = text.Substring(0, getIndexOfFirstEOL(text));
                    titlu = Regex.Replace(titlu, "<[a-zA-Z\\/][^>]*>", "");
                    titlu = titlu.Replace("&nbsp;", " ").Trim();
                    
                    if (nrStelute == 1)
                    {
                        //adaugam nod de nivelul 0 , daca [*]
                        int index = ListaEntitati.Nodes.Add(new EntitateTreeNode(titlu, "anchor_" + element_index, getDate(sub_part)));
                        oldNod = (EntitateTreeNode)ListaEntitati.Nodes[index];
                    }
                    else
                    {   
                        //verificam daca exista un nod principal
                        if(ListaEntitati.Nodes.Count == 0)
                        {
                            //daca nu exista un nod principal iesim din bucla
                            //salvam sursa
                            SaveSource();
                            MessageBox.Show("Primul nod din fiecare document trebuie sa fie principal!");
                            break;
                        }

                        int new_level = nrStelute - 1;
                        if (new_level < oldNod.Level)
                        {
                            TreeNode new_parent = oldNod.Parent;
                            for (int i = 0; i < oldNod.Level - new_level; i++)
                                new_parent = new_parent.Parent;
                            int index = new_parent.Nodes.Add(new EntitateTreeNode(titlu, "anchor_" + element_index, getDate(sub_part)));
                            oldNod = (EntitateTreeNode)new_parent.Nodes[index];
                        }
                        else if (new_level == oldNod.Level)
                        {
                            int index = oldNod.Parent.Nodes.Add(new EntitateTreeNode(titlu, "anchor_" + element_index, getDate(sub_part)));
                            oldNod = (EntitateTreeNode)oldNod.Parent.Nodes[index];
                        }
                        else
                        {
                            int index = oldNod.Nodes.Add(new EntitateTreeNode(titlu, "anchor_" + element_index, getDate(sub_part)));
                            oldNod = (EntitateTreeNode)oldNod.Nodes[index];
                        }
                    }
                    Application.DoEvents();
                    element_index++;
                }
                else
                {
                    int y = text.IndexOf("]");
                    text  = text.Substring(y + 1);
                }
            }
             
            
            SaveFiles();
            pbar.Style = ProgressBarStyle.Continuous; 
        }

        private int getIndexOfFirstEOL(String str)
        {
            int ret = -1;
            //
            List<String> strings = new List<string>();
            strings.Add("\n");
            strings.Add("</br>");
            strings.Add("<br>");
            strings.Add("</p>");

            ret = 1000;
            for (int i = 0; i < strings.Count; i++)
            {
                int index = str.ToLower().IndexOf(strings[i]);
                if (index < ret && index != -1 ) ret = index;
            }
            //
            return ret;
        }

        private void SaveFiles()
        {
            SaveSource();
            SaveXmlFiles();
            SaveGeneratedHtml();
        }

        private void SaveGeneratedHtml()
        {
            // salveaza fisierul html generat
            int x, y, anchor = 0;
            String text1, titlu, text2;

            String text = this.Text;
            String startdiv = "<div {0} {1} {2} >";
            String enddiv = "</div>";

            List<String> titluri = new List<String>();
            List<Div> mydiv = new List<Div>();

            while (text.IndexOf("]") != -1)
            {
                x = text.IndexOf("[");
                if (text[x + 1].Equals('*'))
                {
                    y = text.IndexOf("]");
                    text1 = text.Substring(0, x);
                    string sub_part = text.Substring(x + 1, y - x - 1);
                    text2 = text.Substring(y + 1);
                    titlu = text2.Substring(0, getIndexOfFirstEOL(text2));
                    //sa aflam daca are data , deci daca este o versiune mai veche
                    Div div = new Div();

                    //if (gotDate(sub_part)) 
                    div.StartDiv = x;
                    //
                    text2 = text.Substring(y + 1 + titlu.Length);
                    text2 = titlu + text2;
                    //adauga titlul
                    titluri.Add(titlu);
                    text = text1 + text2;
                    //

                    div.EndDiv = text.IndexOf("[*");
                    if (div.EndDiv == -1) div.EndDiv = text.Length;
                    //adauga div-ul
                    mydiv.Add(div);
                    String t, t1, t2;
                    t = text.Substring(0, div.StartDiv);
                    t1 = text.Substring(div.EndDiv);
                    t2 = text.Substring(div.StartDiv, (div.EndDiv - div.StartDiv));
                    //
                    string sdiv = startdiv;
                    if (gotDate(sub_part))
                        sdiv = String.Format(startdiv, "style='display:none'", "data='" + getDate(sub_part).ToString("dd/MM/yyyy") + "'", "id='anchor_" + anchor + "'");
                    else
                        sdiv = String.Format(startdiv, "style='background:blue'", "", "id='anchor_" + anchor + "'");
                    text = t + sdiv + t2 + enddiv + t1;
                    //
                    anchor++;
                }
                else
                {
                    y    = text.IndexOf("]");
                    text = text.Substring(y + 1);
                }
            }
            //scriem fisierul..
            StreamWriter sw = new StreamWriter("database/files/" + this.ActNormativ.Id + "_generat.htm");
            sw.Write(text);
            sw.Close();
        }

        private void SaveSource()
        {
            StreamWriter sw = new StreamWriter("database/files/" + this.ActNormativ.Id + "_sursa.htm");
            sw.Write(this.Text);
            sw.Close();
        }

        private void SaveXmlFiles()
        {
            //creaza fisierul xml
            XmlDocument doc = new XmlDocument();
            //adauga declaratia
            XmlNode d = doc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
            doc.AppendChild(d);
            //adauga root element
            XmlNode root = doc.CreateElement("", "ROOT", "");
            doc.AppendChild(root);
            //adauga fiecare nod
            foreach (TreeNode nod in ListaEntitati.Nodes)
            {
                EntitateTreeNode tnode = (EntitateTreeNode)nod;
                parseNode(doc, root, tnode);
            }
            //salveaza in [id].xml
            if (this.ActNormativ != null)
                doc.Save("database/files/" + this.ActNormativ.Id + ".xml");

        }

        private void parseNode(XmlDocument doc, XmlNode root, EntitateTreeNode t_node)
        {
            XmlNode xnode = doc.CreateElement("", "nod", "");
            XmlAttribute xattr = doc.CreateAttribute("anchor");
            xattr.Value = t_node.NodeAnchorName;
            XmlText xtext = doc.CreateTextNode(t_node.Text);

            xnode.AppendChild(xtext);
            xnode.Attributes.Append(xattr);
            root.AppendChild(xnode);

            foreach (TreeNode node in t_node.Nodes)
            {
                //adauga fiecare sub-nod al lui xnode
                parseNode(doc, xnode, (EntitateTreeNode)node);
            }
        }

        private int getNrOfChars(char ch, string text)
        {
            int ret = 0;
            foreach (char c in text.ToCharArray())
            {
                if (c.Equals(ch))
                    ret++;
            }

            return ret;
        }

        public static DateTime getDate(String s)
        {
            DateTime data = new DateTime();
            if (s.IndexOf("|") != -1)
            {
                int x = s.IndexOf("|");
                String str = s.Substring(x + 1);
                str = str.Replace("-", "/");
                int w = str.IndexOf("/");
                String wstr = str.Substring(0, w);
                String wstr2 = null;
                //daca ziua este introdusa in format '6' in loc de '06'
                if (wstr.Length < 2)
                {
                    wstr = "0" + wstr;
                    str = str.Substring(w);
                    str = wstr + str;
                    wstr2 = str.Substring(w + 1, str.IndexOf("/"));
                }
                try
                {
                    data = DateTime.ParseExact(str, "dd/MM/yyyy", null);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message + ex.StackTrace);
                }
            }
            return data;
        }

        public static bool gotDate(String s)
        {
            bool ret = false;
            int x = s.IndexOf("|");
            String str = s.Substring(x + 1);
            str = str.Replace("-", "/");
            DateTime data = new DateTime();
            try
            {
                data = DateTime.ParseExact(str, "dd/MM/yyyy", null);
                ret = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace);
            }
            return ret;
        }
    }
}
